/*
 * @Author: xiaozhuang-c-language 3535851673@qq.com
 * @Date: 2025-07-16 10:40:51
 * @LastEditors: xiaozhuang-c-language 3535851673@qq.com
 * @LastEditTime: 2025-10-24 10:20:22
 * @FilePath: /zhuang/BlogSystem/SynAsyLogSystem/Log/Logger.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once
#include"./Message.hpp"
#include"./Level.hpp"
#include"./Looper.hpp"
#include"./Format.hpp"
#include"./Sink.hpp"
#include <atomic>
#include <memory>
#include <mutex>
#include<stdarg.h>
#include<unordered_map>
#include<stdlib.h>
#include<stdio.h>

namespace zlog
{
  class Logger
  {
    public:
        using ptr = shared_ptr<Logger>;
        Logger(const string& logger_name,LogLevel::value level,Formatter::ptr& formatter,
        vector<LogSink::ptr>&sinks):
        _logger_name(logger_name),
        _formatter(formatter),
        _sinks(sinks.begin(),sinks.end()),
        _default_level(level)
        {}
         /* 完成构造日志消息对象过程并进行格式化,得到格式化后的日志消息字符串,然后进行落地输出(行号和文件名，消息是变化的需要提供)*/
         void debug(const string& file,size_t line,const string& fmt,...)
         {
                //1.判断是否大于等于当前日志等级
                if(LogLevel::value::DEBUG < _default_level) return;
                //2.对fmt和不定参进行处理获取日志的有效载荷
                va_list arg;
                va_start(arg,fmt.c_str());
                char* res;
                int ret = vasprintf(&res,fmt.c_str(),arg);
                if(ret == -1)
                {
                    cout << "处理有效载荷失败!" << endl;
                    free(res);
                    abort();
                }
                va_end(arg);
                //3.
                msgSink(file,line,LogLevel::value::DEBUG,res);
         }

         void info(const string& file,size_t line,const string& fmt,...)
         {
                //1.判断是否大于等于当前日志等级
                if(LogLevel::value::INFO < _default_level) return;
                //2.对fmt和不定参进行处理获取日志的有效载荷
                va_list arg;
                va_start(arg,fmt.c_str());
                char* res;
                int ret = vasprintf(&res,fmt.c_str(),arg);
                if(ret == -1)
                {
                    cout << "处理有效载荷失败!" << endl;
                    free(res);
                    abort();
                }
                va_end(arg);
                //3.
                msgSink(file,line,LogLevel::value::INFO,res);
         }

         void warn(const string& file,size_t line,const string& fmt,...)
         {
                //1.判断是否大于等于当前日志等级
                if(LogLevel::value::WARN < _default_level) return;
                //2.对fmt和不定参进行处理获取日志的有效载荷
                va_list arg;
                va_start(arg,fmt.c_str());
                char* res;
                int ret = vasprintf(&res,fmt.c_str(),arg);
                if(ret == -1)
                {
                    cout << "处理有效载荷失败!" << endl;
                    free(res);
                    abort();
                }
                va_end(arg);
                //3.
                msgSink(file,line,LogLevel::value::WARN,res);
         }

         void error(const string& file,size_t line,const string& fmt,...)
         {
                //1.判断是否大于等于当前日志等级
                if(LogLevel::value::ERROR < _default_level) return;
                //2.对fmt和不定参进行处理获取日志的有效载荷
                va_list arg;
                va_start(arg,fmt.c_str());
                char* res;
                int ret = vasprintf(&res,fmt.c_str(),arg);
                if(ret == -1)
                {
                    cout << "处理有效载荷失败!" << endl;
                    free(res);
                    abort();
                }
                va_end(arg);
                //3.
                msgSink(file,line,LogLevel::value::ERROR,res);
         }
         void fatal(const string& file,size_t line,const string& fmt,...)
         {
                //1.判断是否大于等于当前日志等级
                if(LogLevel::value::FATAL < _default_level) return;
                //2.对fmt和不定参进行处理获取日志的有效载荷
                va_list arg;
                va_start(arg,fmt.c_str());
                char* res;
                int ret = vasprintf(&res,fmt.c_str(),arg);
                if(ret == -1)
                {
                    cout << "处理有效载荷失败!" << endl;
                    free(res);
                    abort();
                }
                va_end(arg);
                //3.
                msgSink(file,line,LogLevel::value::FATAL,res);
         }

         string LoggerName()
         {return _logger_name;}

    private:
         void msgSink(const string& file,size_t line,LogLevel::value level, char* res)
         {
            //3.构造LogMsg对象
            LogMsg msg(level,line,file,_logger_name,res);
            //4.使用格式化模块对象对日志消息进行格式化
            string str = _formatter->format(msg);
            //5.进行日志落地
            log(str.c_str(),str.size());
            //注意:最后不要释放res!!!
            free(res);
         }
         
    public:
        /* 抽象接口完成实际的落地输出 --- 不同的日志器会有不同的实际落地方式 */
        virtual void log(const char* data,size_t len) = 0; 
    protected:
       std::mutex _mtx; //保证线程安全的互斥锁
       string _logger_name; //日志器名称
       Formatter::ptr _formatter;//格式化模块对象
       vector<LogSink::ptr> _sinks;//落地模块化对象数组(一个日志器可能同时向多个位置进行日志输出)
       std::atomic<LogLevel::value> _default_level;//默认的日志输出等级
  };

  class SyncLogger : public Logger
  {
    public:
      SyncLogger(const string& logger_name,LogLevel::value level,Formatter::ptr& formatter,
        vector<LogSink::ptr>& sinks)
        :Logger(logger_name,level,formatter,sinks)
        {}

      void log(const char* data,size_t len) override
      {   //加锁保证线程安全
         std::unique_lock<std::mutex> _lock(_mtx);
         if(_sinks.empty()) return; //没有落地方向
         for(auto& sink : _sinks)
         {
             sink->log(data,len);
         }
      }
  };

  class AsyncLogger : public Logger
  {
    public:
      AsyncLogger(const string& logger_name,LogLevel::value level,Formatter::ptr& formatter,
        vector<LogSink::ptr>& sinks,AsyncType looper_type = AsyncType::ASYNC_SAFE)
        :Logger(logger_name,level,formatter,sinks),
         _looper(std::make_shared<AsyncLooper>(std::bind(&AsyncLogger::realLog,this,std::placeholders::_1),looper_type))
        {}
      void log(const char* data,size_t len) override
      {
         _looper->push(data,len);
      }
    private:
       void realLog(Buffer& buf)
       {
         if(_sinks.empty()) return;
         //设置了落地方向
         for(auto& sink : _sinks)
           sink->log(buf.ReadPos(),buf.ReadAbleSize());
       }
    private:
      AsyncLooper::ptr _looper;   
  };


  /* 要建造的日志器类型 */
  enum class LoggerType
  {
     TYPE_SYNC,
     TYPE_ASYNC
  };

  /* 抽象出一个日志器建造者类 */
  class LoggerBuilder
  {
    public:
        ///默认是建造同步日志器，debug限制等级
        LoggerBuilder()
        :_logger_type(LoggerType::TYPE_SYNC),
         _limit_level(LogLevel::value::DEBUG),
         _looper_type(AsyncType::ASYNC_SAFE) //默认是安全模式 
        {}
        void bulidLoggerType(LoggerType type)
        {
             _logger_type = type;
        }
        void bulidLoggerName(const string& logger_name)
        {
              _logger_name = logger_name;
        }
        void buildLimitLevel(LogLevel::value level)
        {
             _limit_level = level;
        }
        void buildFormatter(const string& pattern)
        {
             _formatter = make_shared<Formatter>(pattern);
        }

        template<typename SinkType,typename  ...Args>
        void buildSink(Args&&... args) //注意有可能一个日志器需要多种落地方向，因此一个个构建设置进落地数组里
        {
           LogSink::ptr psink = LogSinkFactory::create<SinkType>(std::forward<Args>(args)...);
           _sinks.push_back(psink);
        }

        void buildEnableUnSafeAsync()
        {
           _looper_type = AsyncType::ASYNC_UNSAFE;
        }

        virtual Logger::ptr build() = 0;//返回日志器对象
    protected:
       LoggerType _logger_type;
       string _logger_name;
       LogLevel::value _limit_level;
       Formatter::ptr _formatter;
       vector<LogSink::ptr> _sinks;
       AsyncType _looper_type;//异步日志器工作模式
  };

  class LocalLoggerBuilder : public LoggerBuilder
  {
    public:
       Logger::ptr build() override
       {
          assert(_logger_name.empty() == false);//1.日志器必须要有
          //2.格式化模块对象没有设置则设置为默认的格式化字符串
          if(_formatter == nullptr)
          _formatter = make_shared<Formatter>("[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n");
          //3.落地数组为空默认为标准输出
          if(_sinks.empty())
          {
            buildSink<StdoutLogSink>();
          }
          //4.根据类型创建同步/异步日志器
          if(_logger_type == LoggerType::TYPE_ASYNC)
             return make_shared<AsyncLogger>(_logger_name,_limit_level,_formatter,_sinks,_looper_type);
          return make_shared<SyncLogger>(_logger_name,_limit_level,_formatter,_sinks);
       }
  };

  /* 日志器管理类 */
  class LoggerManager
  {
    public:
        /* 获取单例对象：前提是C++11静态对象保证线程安全 */
        static LoggerManager& getInstance()
        {
            static LoggerManager manager;
            return manager;
        }

        /* 添加日志管理器 */
        void addLogger(Logger::ptr& logger)
        {
          std::unique_lock<std::mutex> lock(_mtx);
          //1.判断loggername是否合法
          string name = logger->LoggerName();
          if(name == "")
          {
             cout << "日志器名称不合法！" << endl;
             return;
          }
          //2.判断是否已经添加管理了
          if(name.empty() == true) return ;
         //2.在哈希表中查找对应的日志器
          auto it = _loggers.find(name);
          if(it != _loggers.end()) return ;
          //3.没有则进行管理
          _loggers[name] = logger;
        }

        /* 判断是否管理了指定名称的日志器 */
        bool HasManageLogger(const string& name)
        {
          std::unique_lock<std::mutex> lock(_mtx);
         //1.保证name不为空
         if(name.empty() == true) return false;
         //2.在哈希表中查找对应的日志器
          auto it = _loggers.find(name);
          if(it == _loggers.end()) return false;
          return true;
        }

        /* 获取指定名称的日志器 */
        Logger::ptr getLogger(const string& name)
        {
          std::unique_lock<std::mutex> lock(_mtx);
          if(name.empty() == true) return Logger::ptr();
          //2.在哈希表中查找对应的日志器
          auto it = _loggers.find(name);
          if(it == _loggers.end())
          {
            cout << "没有该管理器" << endl;
            return Logger::ptr();
          }
          return _loggers[name];
        }

        /* 获取默认日志器 */
        Logger::ptr getrootLogger()
        {
          return _root_logger;
        }


    private:
       LoggerManager(const LoggerManager& manager) = delete;
       LoggerManager()
       {
          //构造默认日志器
          unique_ptr<zlog::LoggerBuilder> builder(new zlog::LocalLoggerBuilder());
          builder->bulidLoggerName("root_logger");
          _root_logger = builder->build();
          //防止有人通过HasManagerLogger来查找默认日志器，因此将其也添加管理
          _loggers["root_logger"] = _root_logger; 
       }
    private:
      Logger::ptr _root_logger; //默认日志器
      unordered_map<string,Logger::ptr> _loggers;//管理的日志器
      std::mutex _mtx;
  };

  class GlobalLoggerBuilder : public LoggerBuilder
  {
    public:
       Logger::ptr build() override
       {
            assert(_logger_name.empty() == false);//1.日志器必须要有
            //2.格式化模块对象没有设置则设置为默认的格式化字符串
            if(_formatter == nullptr)
            _formatter = make_shared<Formatter>();
            //3.落地数组为空默认为标准输出
            if(_sinks.empty())
            {
               buildSink<StdoutLogSink>();
            }
            Logger::ptr logger;
            //4.根据类型创建同步/异步日志器
            if(_logger_type == LoggerType::TYPE_ASYNC)
               logger = make_shared<AsyncLogger>(_logger_name,_limit_level,_formatter,_sinks,_looper_type);
            else 
               logger = make_shared<SyncLogger>(_logger_name,_limit_level,_formatter,_sinks);
            //添加到单例管理类进行管理(哈希表中有logger的拷贝因此管理对象不会被释放)
            LoggerManager::getInstance().addLogger(logger);
            return logger;
       }
  };

}